/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						 metatile_map.cpp

	$Header: /heroes4/metatile_map.cpp $

	$NoKeywords: $

 ************************************************************************/

#include "precompiled.h"
#pragma warning( disable: 4786 )

#include "metatile_map.h"

#include <algorithm>
#include <functional>

#include "enum_operations.h"
#include "metatile_texture.h"
#include "metatile_texture_cache.h"
#include "random_number_generator.h"
#include "static_vector.h"

// --------------------------------------------------------------------------
// Unnamed namespace
// --------------------------------------------------------------------------

namespace
{

	// --------------------------------------------------------------------------
	// t_intersecting_metatile_info struct
	// --------------------------------------------------------------------------

	struct t_intersecting_metatile_info
	{
		// Data members
		t_map_point_2d	point;
		int				ordinal;
		bool			full_tile;

		// Constructor
		t_intersecting_metatile_info(
			t_map_point_2d const &	point_arg,
			int						ordinal_arg,
			bool					full_tile_arg );
	};

	inline t_intersecting_metatile_info::t_intersecting_metatile_info(
		t_map_point_2d const &	point_arg,
		int						ordinal_arg,
		bool					full_tile_arg )
		:	point( point_arg ),
			ordinal( ordinal_arg ),
			full_tile( full_tile_arg )
	{
	}

	// --------------------------------------------------------------------------
	// t_intersecting_metatile_info_ordinal_compare struct
	// --------------------------------------------------------------------------

	struct t_intersecting_metatile_info_ordinal_compare
		:	public std::binary_function< t_intersecting_metatile_info, t_intersecting_metatile_info, bool >
	{
		// Operator
		bool operator()( t_intersecting_metatile_info const & first, t_intersecting_metatile_info const & second ) const;
	};

	inline bool t_intersecting_metatile_info_ordinal_compare::operator()(
		t_intersecting_metatile_info const & first,
		t_intersecting_metatile_info const & second ) const
	{
		return first.ordinal > second.ordinal;
	}

} // Unnamed namespace

// --------------------------------------------------------------------------
// t_metatile_map::t_impl class
// --------------------------------------------------------------------------

class t_metatile_map::t_impl
{
public:
	// Types
	struct t_row_data
	{
		int	offset;
		int	start;
		int	end;
	};

	typedef t_static_vector< t_static_vector< t_tile_info, k_metatile_logical_size >, k_metatile_logical_size > t_metatile_tile_info_array;

	struct t_metatile_data
	{
		t_metatile_info				info;
		t_metatile_tile_info_array	tile_info_array;
	};

	// Data members
	int								m_num_levels;
	int								m_level_size;
	std::vector< t_row_data >		m_row_data_vector;
	std::vector< t_metatile_data >	m_metatile_data_vector;

	// Constructor
	t_impl( t_abstract_tile_map const & tile_map, long random_seed );

	// Member functions
	int					compute_metatile_index( t_level_map_point_2d const & metatile_point ) const;
	t_metatile_data &	get_metatile_data( t_level_map_point_2d const & metatile_point );
	t_metatile_info &	get_metatile_info( t_level_map_point_2d const & metatile_point );
	t_tile_info &		get_tile_info( t_level_map_point_2d const & tile_point );
	void				randomize_metatile_data( long random_seed );
};

// --------------------------------------------------------------------------
// t_metatile_map::t_impl members
// --------------------------------------------------------------------------

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
t_metatile_map::t_impl::t_impl( t_abstract_tile_map const & tile_map, long random_seed )
	:	m_level_size( 0 )
{
	// Compute the logical size of the metatile map
	int tile_map_size;
	tile_map.get_size( tile_map_size, m_num_levels );
	int size = ( tile_map_size + k_metatile_logical_size - 1 ) / k_metatile_logical_size;
	m_row_data_vector.resize( size );

	// Compute the bounds of the rows of the metatile map and the level data size
	int metatile_row;
	for ( metatile_row = 0; metatile_row < size; ++metatile_row )
	{
		t_row_data & row_data = m_row_data_vector[ metatile_row ];

		row_data.start = size;
		row_data.end = 0;

		int tile_row;
		for (	tile_row = metatile_row * k_metatile_logical_size;
				tile_row < ( metatile_row + 1 ) * k_metatile_logical_size;
				++tile_row )
		{
			if ( tile_row >= tile_map_size )
			{
				assert( metatile_row == size - 1 );
				break;
			}

			int tile_row_start;
			int tile_row_end;
			tile_map.get_row_bounds( tile_row, tile_row_start, tile_row_end );
			assert( tile_row_end > tile_row_start );

			int new_metatile_row_start = tile_row_start / k_metatile_logical_size;
			int new_metatile_row_end = ( tile_row_end + k_metatile_logical_size - 1 ) / k_metatile_logical_size;

			if ( new_metatile_row_start < row_data.start )
				row_data.start = new_metatile_row_start;

			if ( new_metatile_row_end > row_data.end )
				row_data.end = new_metatile_row_end;
		}

		assert( row_data.end > row_data.start );
		row_data.offset = m_level_size - row_data.start;
		m_level_size += row_data.end - row_data.start;
	}

	m_metatile_data_vector.resize( m_num_levels * m_level_size );

	randomize_metatile_data( random_seed );
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline int t_metatile_map::t_impl::compute_metatile_index( t_level_map_point_2d const & metatile_point ) const
{
	assert( metatile_point.level >= 0 && metatile_point.level < m_num_levels );
	assert( metatile_point.row >= 0 && metatile_point.row < m_row_data_vector.size() );

	t_row_data const & row_data = m_row_data_vector[ metatile_point.row ];

	assert( metatile_point.column >= row_data.start && metatile_point.column < row_data.end );

	return metatile_point.level * m_level_size + row_data.offset + metatile_point.column;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline t_metatile_map::t_impl::t_metatile_data & t_metatile_map::t_impl::get_metatile_data( t_level_map_point_2d const & metatile_point )
{
	return m_metatile_data_vector[ compute_metatile_index( metatile_point ) ];
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline t_metatile_map::t_metatile_info & t_metatile_map::t_impl::get_metatile_info( t_level_map_point_2d const & metatile_point )
{
	return m_metatile_data_vector[ compute_metatile_index( metatile_point ) ].info;
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
inline t_metatile_map::t_tile_info & t_metatile_map::t_impl::get_tile_info( t_level_map_point_2d const & tile_point )
{
	t_level_map_point_2d	metatile_point(
								tile_point.row / k_metatile_logical_size,
								tile_point.column / k_metatile_logical_size,
								tile_point.level );

	t_metatile_data & metatile_data = m_metatile_data_vector[ compute_metatile_index( metatile_point ) ];
	return metatile_data.tile_info_array[ tile_point.column % k_metatile_logical_size ][ tile_point.row % k_metatile_logical_size ];
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
void t_metatile_map::t_impl::randomize_metatile_data( long random_seed )
{
	t_random_number_generator rng( random_seed );

	std::vector< int > ordinal_vector( m_num_levels * m_level_size );
	int ordinal;
	for ( ordinal = 0; ordinal < ordinal_vector.size(); ++ordinal )
		ordinal_vector[ ordinal ] = ordinal;
	std::random_shuffle( ordinal_vector.begin(), ordinal_vector.end(), rng );

	// Setup the metatile info
	std::vector< t_metatile_data >::iterator metatile_data_iter = m_metatile_data_vector.begin();
	for ( ; metatile_data_iter != m_metatile_data_vector.end(); ++metatile_data_iter )
	{
		t_metatile_info & metatile_info = metatile_data_iter->info;

		// Randomize the texture numbers for each of the terrain types in this metatile
		t_terrain_type terrain_type;
		for ( terrain_type = t_terrain_type( 0 ); terrain_type < k_terrain_count; enum_incr( terrain_type ) )
		{
			int terrain_subtype_count = get_terrain_subtype_count( terrain_type );
			int terrain_subtype;
			for ( terrain_subtype = 0; terrain_subtype < terrain_subtype_count; ++terrain_subtype )
			{
				int texture_num = rng() % get_metatile_texture_count( terrain_type, terrain_subtype );
				metatile_info.set_texture_num( terrain_type, terrain_subtype, texture_num );
			}
		}

		// Randomize the texture numbers for each of the road types in this metatile
		t_road_type road_type;
		for ( road_type = t_road_type( 1 ); road_type < k_road_type_count; enum_incr( road_type ) )
		{
			int texture_num = rng() % get_metatile_texture_count( road_type );
			metatile_info.set_texture_num( road_type, texture_num );
		}

		// Randomize the metatile offset
		t_map_point_2d	new_offset(
							rng() % ( k_metatile_max_offset + 1 ),
							rng() % ( k_metatile_max_offset + 1 ) );
		metatile_info.set_offset( new_offset );
	}

	t_level_map_point_2d metatile_point;
	for (	metatile_point.level = 0;
			metatile_point.level < m_num_levels;
			++metatile_point.level )
	{
		for (	metatile_point.row = 0;
				metatile_point.row < m_row_data_vector.size();
				++metatile_point.row )
		{
			t_row_data const & row_data = m_row_data_vector[ metatile_point.row ];
			for (	metatile_point.column = row_data.start;
					metatile_point.column < row_data.end;
					++metatile_point.column )
			{
				int metatile_index = compute_metatile_index( metatile_point );
				t_metatile_data & metatile_data = m_metatile_data_vector[ metatile_index ];
				int base_ordinal = ordinal_vector[ metatile_index ];

				t_map_point_2d relative_tile_point;
				for (	relative_tile_point.column = 0;
						relative_tile_point.column < k_metatile_logical_size;
						++relative_tile_point.column )
				{
					for (	relative_tile_point.row = 0;
							relative_tile_point.row < k_metatile_logical_size;
							++relative_tile_point.row )
					{
						// Build a vector of info about the metatiles that intersect this tile
						std::vector< t_intersecting_metatile_info > intersecting_metatile_info_vector;
						intersecting_metatile_info_vector.push_back( t_intersecting_metatile_info( metatile_point, base_ordinal, true ) );

						// Look at the metatile to the northeast
						if (	relative_tile_point.row
							<	k_metatile_texture_border_size + k_metatile_max_offset )
						{
							t_level_map_point_2d adj_metatile_point = metatile_point;
							--adj_metatile_point.row;
							if ( adj_metatile_point.row >= 0 )
							{
								t_row_data const & adj_row_data = m_row_data_vector[ adj_metatile_point.row ];
								if (	adj_metatile_point.column >= adj_row_data.start
									&&	adj_metatile_point.column < adj_row_data.end )
								{
									int adj_metatile_index = compute_metatile_index( adj_metatile_point );
									t_metatile_data const & adj_metatile_data = m_metatile_data_vector[ adj_metatile_index ];
									int adj_ordinal = ordinal_vector[ adj_metatile_index ];
									t_map_point_2d adj_offset = adj_metatile_data.info.get_offset();

									if (	adj_ordinal > base_ordinal
										&&		relative_tile_point.row
											<	k_metatile_texture_border_size + adj_offset.row )
									{
										intersecting_metatile_info_vector.push_back(
											t_intersecting_metatile_info(
												adj_metatile_point,
												adj_ordinal,
												relative_tile_point.row < adj_offset.row ) );
									}
								}
							}
						}

						// Look at the metatile to the southwest
						if (	relative_tile_point.row
							>=	k_metatile_logical_size - k_metatile_texture_border_size - k_metatile_max_offset )
						{
							t_level_map_point_2d adj_metatile_point = metatile_point;
							++adj_metatile_point.row;
							if ( adj_metatile_point.row < m_row_data_vector.size() )
							{
								t_row_data const & adj_row_data = m_row_data_vector[ adj_metatile_point.row ];
								if (	adj_metatile_point.column >= adj_row_data.start
									&&	adj_metatile_point.column < adj_row_data.end )
								{
									int adj_metatile_index = compute_metatile_index( adj_metatile_point );
									t_metatile_data const & adj_metatile_data = m_metatile_data_vector[ adj_metatile_index ];
									int adj_ordinal = ordinal_vector[ adj_metatile_index ];
									t_map_point_2d adj_offset = adj_metatile_data.info.get_offset();

									if (	adj_ordinal > base_ordinal
										&&		relative_tile_point.row
											>=		k_metatile_logical_size
												-	k_metatile_texture_border_size
												-	k_metatile_max_offset
												+	adj_offset.row )
									{
										intersecting_metatile_info_vector.push_back(
											t_intersecting_metatile_info(
												adj_metatile_point,
												adj_ordinal,
													relative_tile_point.row
												>=	k_metatile_logical_size - k_metatile_max_offset + adj_offset.row ) );
									}
								}
							}
						}

						// Look at the metatile to the northwest
						if (	relative_tile_point.column
							<	k_metatile_texture_border_size + k_metatile_max_offset )
						{
							t_level_map_point_2d adj_metatile_point = metatile_point;
							--adj_metatile_point.column;
							if ( adj_metatile_point.column >= row_data.start )
							{
								int adj_metatile_index = compute_metatile_index( adj_metatile_point );
								t_metatile_data const & adj_metatile_data = m_metatile_data_vector[ adj_metatile_index ];
								int adj_ordinal = ordinal_vector[ adj_metatile_index ];
								t_map_point_2d adj_offset = adj_metatile_data.info.get_offset();

								if (	adj_ordinal > base_ordinal
									&&		relative_tile_point.column
										<	k_metatile_texture_border_size + adj_offset.column )
								{
									intersecting_metatile_info_vector.push_back(
										t_intersecting_metatile_info(
											adj_metatile_point,
											adj_ordinal,
											relative_tile_point.column < adj_offset.column ) );
								}
							}
						}

						// Look at the metatile to the southwest
						if (	relative_tile_point.column
							>=	k_metatile_logical_size - k_metatile_texture_border_size - k_metatile_max_offset )
						{
							t_level_map_point_2d adj_metatile_point = metatile_point;
							++adj_metatile_point.column;
							if ( adj_metatile_point.column < row_data.end )
							{
								int adj_metatile_index = compute_metatile_index( adj_metatile_point );
								t_metatile_data const & adj_metatile_data = m_metatile_data_vector[ adj_metatile_index ];
								int adj_ordinal = ordinal_vector[ adj_metatile_index ];
								t_map_point_2d adj_offset = adj_metatile_data.info.get_offset();

								if (	adj_ordinal > base_ordinal
									&&		relative_tile_point.column
										>=		k_metatile_logical_size
											-	k_metatile_texture_border_size
											-	k_metatile_max_offset
											+	adj_offset.column )
								{
									intersecting_metatile_info_vector.push_back(
										t_intersecting_metatile_info(
											adj_metatile_point,
											adj_ordinal,
												relative_tile_point.column
											>=	k_metatile_logical_size - k_metatile_max_offset + adj_offset.column ) );
								}
							}
						}

						// Look at the metatile to the north
						if (		relative_tile_point.row
								<	k_metatile_texture_border_size + k_metatile_max_offset
							&&		relative_tile_point.column
								<	k_metatile_texture_border_size + k_metatile_max_offset )
						{
							t_level_map_point_2d adj_metatile_point = metatile_point;
							--adj_metatile_point.row;
							--adj_metatile_point.column;
							if ( adj_metatile_point.row >= 0 )
							{
								t_row_data const & adj_row_data = m_row_data_vector[ adj_metatile_point.row ];
								if (	adj_metatile_point.column >= adj_row_data.start
									&&	adj_metatile_point.column < adj_row_data.end )
								{
									int adj_metatile_index = compute_metatile_index( adj_metatile_point );
									t_metatile_data const & adj_metatile_data = m_metatile_data_vector[ adj_metatile_index ];
									int adj_ordinal = ordinal_vector[ adj_metatile_index ];
									t_map_point_2d adj_offset = adj_metatile_data.info.get_offset();

									if (	adj_ordinal > base_ordinal
										&&		relative_tile_point.row
											<	k_metatile_texture_border_size + adj_offset.row
										&&		relative_tile_point.column
											<	k_metatile_texture_border_size + adj_offset.column )
									{
										intersecting_metatile_info_vector.push_back(
											t_intersecting_metatile_info(
												adj_metatile_point,
												adj_ordinal,
													relative_tile_point.row < adj_offset.row
												&&	relative_tile_point.column < adj_offset.column ) );
									}
								}
							}
						}

						// Look at the metatile to the east
						if (		relative_tile_point.row
								<	k_metatile_texture_border_size + k_metatile_max_offset
							&&		relative_tile_point.column
								>=	k_metatile_logical_size - k_metatile_texture_border_size - k_metatile_max_offset )
						{
							t_level_map_point_2d adj_metatile_point = metatile_point;
							--adj_metatile_point.row;
							++adj_metatile_point.column;
							if ( adj_metatile_point.row >= 0 )
							{
								t_row_data const & adj_row_data = m_row_data_vector[ adj_metatile_point.row ];
								if (	adj_metatile_point.column >= adj_row_data.start
									&&	adj_metatile_point.column < adj_row_data.end )
								{
									int adj_metatile_index = compute_metatile_index( adj_metatile_point );
									t_metatile_data const & adj_metatile_data = m_metatile_data_vector[ adj_metatile_index ];
									int adj_ordinal = ordinal_vector[ adj_metatile_index ];
									t_map_point_2d adj_offset = adj_metatile_data.info.get_offset();

									if (	adj_ordinal > base_ordinal
										&&		relative_tile_point.row
											<	k_metatile_texture_border_size + adj_offset.row
										&&		relative_tile_point.column
											>=		k_metatile_logical_size
												-	k_metatile_texture_border_size
												-	k_metatile_max_offset
												+	adj_offset.column )
									{
										intersecting_metatile_info_vector.push_back(
											t_intersecting_metatile_info(
												adj_metatile_point,
												adj_ordinal,
													relative_tile_point.row < adj_offset.row
												&&		relative_tile_point.column
													>=	k_metatile_logical_size - k_metatile_max_offset + adj_offset.column ) );
									}
								}
							}
						}

						// Look at the metatile to the west
						if (		relative_tile_point.row
								>=	k_metatile_logical_size - k_metatile_texture_border_size - k_metatile_max_offset
							&&		relative_tile_point.column
								<	k_metatile_texture_border_size + k_metatile_max_offset )
						{
							t_level_map_point_2d adj_metatile_point = metatile_point;
							++adj_metatile_point.row;
							--adj_metatile_point.column;
							if ( adj_metatile_point.row < m_row_data_vector.size() )
							{
								t_row_data const & adj_row_data = m_row_data_vector[ adj_metatile_point.row ];
								if (	adj_metatile_point.column >= adj_row_data.start
									&&	adj_metatile_point.column < adj_row_data.end )
								{
									int adj_metatile_index = compute_metatile_index( adj_metatile_point );
									t_metatile_data const & adj_metatile_data = m_metatile_data_vector[ adj_metatile_index ];
									int adj_ordinal = ordinal_vector[ adj_metatile_index ];
									t_map_point_2d adj_offset = adj_metatile_data.info.get_offset();

									if (	adj_ordinal > base_ordinal
										&&		relative_tile_point.row
											>=		k_metatile_logical_size
												-	k_metatile_texture_border_size
												-	k_metatile_max_offset
												+	adj_offset.row
										&&		relative_tile_point.column
											<	k_metatile_texture_border_size + adj_offset.column )
									{
										intersecting_metatile_info_vector.push_back(
											t_intersecting_metatile_info(
												adj_metatile_point,
												adj_ordinal,
														relative_tile_point.row
													>=	k_metatile_logical_size - k_metatile_max_offset + adj_offset.row
												&&	relative_tile_point.column < adj_offset.column ) );
									}
								}
							}
						}

						// Look at the metatile to the south
						if (		relative_tile_point.row
								>=	k_metatile_logical_size - k_metatile_texture_border_size - k_metatile_max_offset
							&&		relative_tile_point.column
								>=	k_metatile_logical_size - k_metatile_texture_border_size - k_metatile_max_offset )
						{
							t_level_map_point_2d adj_metatile_point = metatile_point;
							++adj_metatile_point.row;
							++adj_metatile_point.column;
							if ( adj_metatile_point.row < m_row_data_vector.size() )
							{
								t_row_data const & adj_row_data = m_row_data_vector[ adj_metatile_point.row ];
								if (	adj_metatile_point.column >= adj_row_data.start
									&&	adj_metatile_point.column < adj_row_data.end )
								{
									int adj_metatile_index = compute_metatile_index( adj_metatile_point );
									t_metatile_data const & adj_metatile_data = m_metatile_data_vector[ adj_metatile_index ];
									int adj_ordinal = ordinal_vector[ adj_metatile_index ];
									t_map_point_2d adj_offset = adj_metatile_data.info.get_offset();

									if (	adj_ordinal > base_ordinal
										&&		relative_tile_point.row
											>=		k_metatile_logical_size
												-	k_metatile_texture_border_size
												-	k_metatile_max_offset
												+	adj_offset.row
										&&		relative_tile_point.column
											>=		k_metatile_logical_size
												-	k_metatile_texture_border_size
												-	k_metatile_max_offset
												+	adj_offset.column )
									{
										intersecting_metatile_info_vector.push_back(
											t_intersecting_metatile_info(
												adj_metatile_point,
												adj_ordinal,
														relative_tile_point.row
													>=	k_metatile_logical_size - k_metatile_max_offset + adj_offset.row
												&&		relative_tile_point.column
													>=	k_metatile_logical_size - k_metatile_max_offset + adj_offset.column ) );
									}
								}
							}
						}

						// Sort the intersecting metatile positions
						std::sort(
							intersecting_metatile_info_vector.begin(),
							intersecting_metatile_info_vector.end(),
							t_intersecting_metatile_info_ordinal_compare() );

						// Look fo the first full intersecting tile
						std::vector< t_intersecting_metatile_info >::const_iterator intersecting_metatile_info_iter;
						for (	intersecting_metatile_info_iter = intersecting_metatile_info_vector.begin();
								true;
								++intersecting_metatile_info_iter )
						{
							assert( intersecting_metatile_info_iter != intersecting_metatile_info_vector.end() );

							if ( intersecting_metatile_info_iter->full_tile )
							{
								++intersecting_metatile_info_iter;
								break;
							}
						}

						// Create the intersecting metatile point vector
						std::vector< t_map_point_2d > intersecting_metatile_point_vector;
						intersecting_metatile_point_vector.reserve( intersecting_metatile_info_iter - intersecting_metatile_info_vector.begin() );
						while ( intersecting_metatile_info_iter != intersecting_metatile_info_vector.begin() )
						{
							--intersecting_metatile_info_iter;
							intersecting_metatile_point_vector.push_back( intersecting_metatile_info_iter->point );
						}

						t_tile_info & tile_info = metatile_data.tile_info_array[ relative_tile_point.column ][ relative_tile_point.row ];
						tile_info.set_intersecting_metatile_points( intersecting_metatile_point_vector );
					}
				}
			}
		}
	}
}

// --------------------------------------------------------------------------
// t_metatile_map members
// --------------------------------------------------------------------------

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
t_metatile_map::t_metatile_map( t_abstract_tile_map const & tile_map, long random_seed )
	:	m_impl_ptr( new t_impl( tile_map, random_seed ) )
{
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
t_metatile_map::t_metatile_map( t_metatile_map const & other )
	:	m_impl_ptr( new t_impl( *other.m_impl_ptr ) )
{
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
t_metatile_map::~t_metatile_map()
{
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
t_metatile_map::t_metatile_info const & t_metatile_map::get_metatile_info( t_level_map_point_2d const & metatile_point ) const
{
	return m_impl_ptr->get_metatile_info( metatile_point );
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
t_metatile_map::t_tile_info const & t_metatile_map::get_tile_info( t_level_map_point_2d const & tile_point ) const
{
	return m_impl_ptr->get_tile_info( tile_point );
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
t_metatile_map & t_metatile_map::operator=( t_metatile_map const & other )
{
	m_impl_ptr.reset( new t_impl( *other.m_impl_ptr ) );
	return *this;
}

// --------------------------------------------------------------------------
// t_metatile_map::t_tile_info members
// --------------------------------------------------------------------------

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
t_metatile_map::t_tile_info::t_tile_info( t_tile_info const & other )
	:	m_metatile_point_count( other.m_metatile_point_count )
{
	if ( m_metatile_point_count > 0 )
	{
		assert( other.m_metatile_points.get() != 0 );
		m_metatile_points.reset( new t_point [ m_metatile_point_count ] );
		std::copy(
			other.m_metatile_points.get(),
			other.m_metatile_points.get() + m_metatile_point_count,
			m_metatile_points.get() );
	}
}

// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
void t_metatile_map::t_tile_info::set_intersecting_metatile_points(
	std::vector< t_map_point_2d > const &	new_metatile_point_vector )
{
	t_owned_array< t_point > new_metatile_points;
		
	if ( !new_metatile_point_vector.empty() )
	{
		new_metatile_points.reset( new t_point [ new_metatile_point_vector.size() ] );

		std::vector< t_map_point_2d >::const_iterator src_point_end = new_metatile_point_vector.end();
		std::vector< t_map_point_2d >::const_iterator src_point_iter = new_metatile_point_vector.begin();
		t_point * dest_point_iter = new_metatile_points.get();
		for ( ; src_point_iter != src_point_end; ++src_point_iter, ++dest_point_iter )
		{
			dest_point_iter->row = src_point_iter->row;
			dest_point_iter->col = src_point_iter->column;
		}
	}

	m_metatile_points.swap( new_metatile_points );
	m_metatile_point_count = new_metatile_point_vector.size();
}
